﻿using System;
using System.Collections.Generic;
using UnityEngine;
using winS.Unity.Process;
using winS.winML;

namespace winS.UnityEditor.ProcessEditor
{
    public class ProcessEditorData
    {
        public bool saveOnClose = true;
        public bool saveOnSwitch = true;

        public HistoryData historyData = new HistoryData();
        public FileViewData fileViewData = new FileViewData();
        public BackgroundData backgroundData = new BackgroundData();
        public SelectionSetting selectionSetting = new SelectionSetting();
        public ConnectionLineSetting connectionLineSetting = new ConnectionLineSetting();

        public class HistoryData
        {
            public Action onClear;

            public int maxHistory = 20;
            public List<string> historyList = new List<string>();

            public void Clear()
            {
                historyList.Clear();
                onClear?.Invoke();
            }
        }
        public class FileViewData
        {
            [WinMLSerializable]
            private readonly Dictionary<string, FileViewDataInfo> fileViewDataInfoDictionary = new Dictionary<string, FileViewDataInfo>();

            public ViewData Load(EditorProcessInfo editorProcessInfo)
            {
                string fullPath = EditorAssetManager.ProjectPathToFullPath(editorProcessInfo.pathRelativeProject);
                //虽然有对应路径的数据, 但可能是同路径下的不同文件(比如在保存后, 删除了该文件, 然后创建了一个同名文件), 继续检查
                if (fileViewDataInfoDictionary.TryGetValue(fullPath, out FileViewDataInfo fileViewDataInfo) && fileViewDataInfo.md5 == Cryptography.OneWayEncryption.CreateMD5FromFile(fullPath)) return fileViewDataInfo.viewData;
                return new ViewData();
            }
            public void Save(EditorProcessInfo editorProcessInfo, ViewData viewData)
            {
                string fullPath = EditorAssetManager.ProjectPathToFullPath(editorProcessInfo.pathRelativeProject);
                fileViewDataInfoDictionary[fullPath] = new FileViewDataInfo(Cryptography.OneWayEncryption.CreateMD5FromFile(fullPath), viewData);
            }

            private readonly struct FileViewDataInfo
            {
                public readonly string md5;
                public readonly ViewData viewData;

                public FileViewDataInfo(string md5, ViewData viewData)
                {
                    this.md5 = md5;
                    this.viewData = viewData;
                }
            }
        }
        public class BackgroundData
        {
            public static float lineWidthDefaultValue = 1f;
            public static float minIntervalDefaultValue = 10f;
            public static float maxIntervalDefaultValue = 40f;
            public static int rulerlineIntervalDefaultValue = 5;

            public static Color lineColorDefaultValue = new Color32(193, 196, 192, 25);
            public static Color rulerlineColorDefaultValue = new Color32(193, 196, 192, 55);
            public static Color backgroundColorDefaultValue = new Color32(43, 43, 43, 255);

            public float lineWidth = lineWidthDefaultValue;
            public float minInterval = minIntervalDefaultValue;
            public float maxInterval = maxIntervalDefaultValue;
            public int rulerlineInterval = rulerlineIntervalDefaultValue;

            public Color lineColor = lineColorDefaultValue;
            public Color rulerlineColor = rulerlineColorDefaultValue;
            public Color backgroundColor = backgroundColorDefaultValue;
        }
        public class SelectionSetting
        {
            public static readonly Color defaultSelectBoxColor = new Color32(255, 153, 0, 255);

            public SettableValue<Color> selectBoxColor = new SettableValue<Color>(defaultSelectBoxColor);
        }
        public class ConnectionLineSetting
        {
            public static readonly Color defaultNormalColor = new Color32(132, 228, 231, 255);
            public static readonly Color defaultHighlightColor = new Color32(0, 255, 112, 255);

            public SettableValue<Color> normalColor = new SettableValue<Color>(defaultNormalColor);
            public SettableValue<Color> highlightColor = new SettableValue<Color>(defaultHighlightColor);
        }

        public class SettableValue<T>
        {
            public event Action<T> onValueChanged;

            public T defaultValue { get; private set; }
            public T value { get => _value; set => SetValue(value); }

            [WinMLSerializable]
            private T _value;

            public SettableValue(T defaultValue)
            {
                this.defaultValue = _value = defaultValue;
            }

            public void Reset()
            {
                value = defaultValue;
            }
            public void SetValueWithoutNotify(T newValue)
            {
                _value = newValue;
            }

            public override string ToString()
            {
                return value.ToString();
            }

            private void SetValue(T newValue)
            {
                _value = newValue;
                onValueChanged?.Invoke(value);
            }

            public static implicit operator T(SettableValue<T> self)
            {
                return self.value;
            }
        }
    }
}